<?php
	class RouteComponent {		private $childs = null;
		private $params = null;
		private $parameter = null;

		function __construct() {			$this->childs = array();
			$this->params = array(
					'controller' => 'Main',
					'action' => 'UnknownRoute'
				);
			$this->parameter = null;		}

		public function Map($uri, $params) {			if(count($uri) < 1) {				$this->SetParams($params);				return;			}
        	$item = array_shift($uri);

			if($item[0]!=':') {
	        	if(isset($this->childs[$item])) {	        		$this->childs[$item]->map($uri, $params);
	        		return;	        	}
        	} else {        		$item = substr($item, 1, strlen($item)-1);
        		if(!$this->parameter) {        			$this->parameter = new RouteParamComponent($item);        		}

        		if($this->parameter->Name()!=$item)
        			throw new Exception("Parameter name protected!");

        		$this->parameter->Map($uri, $params);        	}

        	$child = new RouteComponent();
            $child->map($uri, $params);
            $this->childs[$item] = $child;		}

		private function SetParams($params) {			foreach($params as $p => $v) {				$this->params[$p] = $v;			}		}

		public function Check($uri) {			if(count($uri)<1) {				return $this->params;			}

			$item = array_shift($uri);

			if(!isset($this->childs[$item])) {				if(!$this->parameter) {					$x = $this->params;
					array_unshift($uri, $item);
	                $x['lostPath'] = $uri/*implode('/', $uri)*/;
					return $x;
				}

       			return $this->parameter->Check($uri, $item);			}

			return $this->childs[$item]->Check($uri);		}	}

	final class RouteParamComponent extends RouteComponent{		private $name = null;		function __construct($pname) {			parent::__construct();
			$this->name = $pname;		}

		public function Name() {			return $this->name;		}

		public function Check($uri, $paramValue) {			$res = parent::Check($uri);
			$res[$this->name] = $paramValue;
			return $res;		}	}

	final class Router{		private $root = null;
		function __construct() {        	$this->root = new RouteComponent();
        	$this->root->Map(array(), array('action' => 'Index'));		}

		public function Map($uri, $params) {			$items = $this->parseUri($uri)->items;
			$this->root->Map($items, $params);		}

		public function Check($uri) {			$puri = $this->parseUri($uri);
  			$res = $this->root->Check($puri->items);
  			$res['asXML'] = $puri->asXML?'yes':'no';
  			return $res;		}

		private function parseUri($uri) {			$res = new stdClass();
			$res->asXML = false;
			$turi = $uri;			$pos = strpos($turi, '?');
			if($pos) $turi = substr($turi, 0, $pos);
			$pos = strpos($turi, '==XML');
			if($pos) $turi = substr($turi, 0, $pos);
			$res->asXML = (bool)$pos;

			$items = explode('/', $turi);
			if($items[0]=='') array_shift($items);
			$c = count($items);
			if($c && $items[$c-1]=='') {				array_pop($items);			}

			$res->items = $items;
			return $res;		}	}
?>